#ifndef BOOST_FS_IMPL
#define BOOST_FS_IMPL

#include <boost/filesystem.hpp>

namespace adapters { namespace details {

	namespace fs = boost::filesystem;

	inline bool nativeExists(std::string const & name)
	try {
		return fs::exists(name);		
	} catch (...) {
		return false;
	}

#if defined (USE_BOOST_FILE_SYSTEM_V3)
#	define BOOST_FILESYSTEM_VERSION 3
	inline bool BoostRename(std::string const & from, std::string const & to) {
		boost::system::error_code err;
		fs::rename(from, to, err);		
		if (err) 
			return false;
		return true;
	}
	inline std::string BoostHiddenMakeFileName(std::string const & fileName, char const filePrefix){
		fs::path oldpath(path);
		fs::path newName(oldpath.parent_path());
	    std::string fileName = filePrefix + oldpath.native();
		newName.append(fileName.begin(), fileName.end());
        return newName.string();
	}
#else

	inline bool BoostRename(std::string const & from, std::string const & to) 
	try {
		fs::rename(from, to);	
		return true;
	}catch(...){
		return false;
	}

	inline std::string BoostHiddenMakeFileName(std::string const & path, char const filePrefix) {
		fs::path oldpath(path);
		fs::path newName(oldpath.parent_path());
	    std::string fileName = filePrefix + oldpath.filename();
		newName.append(fileName.begin(), fileName.end());
        return newName.string();
	}

#endif

	inline boost::intmax_t nativeFileSize(std::string const & fileName) {
		boost::intmax_t size = 0; 
		try {
			if (!nativeExists(fileName))
				return -1;
			size = fs::file_size(fileName);
		} catch (...) {
			return -1;
		}
		return size;
	}

	inline bool nativeRename(std::string const & from, std::string const & to) {
		return BoostRename(from, to);
	}
		
	inline bool nativeRemove(std::string const & fileName)
	try {
		//if (!nativeExists(fileName))
		//	return false;
		fs::remove(fileName);	
		return true;
	} catch (...) {
		return false;
	}

	bool safeSwap(std::string const & /*first*/, std::string const & /*second*/) {
		// TODO : impl this
		return true;
	}

	bool hardSwap(std::string const & first, std::string const & second) {
		if (!nativeRemove(first))
			return false;
		if(!nativeRename(first, second))
			return false;
		return true;
	}

	inline bool nativeSwap(std::string const & first, std::string const & second, bool const safe) {
		return !safe ? safeSwap(first, second) : hardSwap(first, second);
	}
		
	inline bool nativeCreateDir(std::string const & fileName)
	try {
		if (nativeExists(fileName))
			return false;
		fs::create_directory(fileName);		
		return true;
	} catch (...) {
		return false;
	}


	inline std::string nativeHiddenMakeFileName(std::string const & fileName, char const filePrefix) {	
		return BoostHiddenMakeFileName(fileName, filePrefix);
	}


#if defined (WIN32) || defined (WIN64)
#	include <windows.h>
#	define FS_HAS_OS_API_SUPPORT
	
	inline bool apiHideFile(std::string const & fileName) {
		return SetFileAttributesA(fileName.c_str(), FILE_ATTRIBUTE_HIDDEN) != 0 ? true : false;
	}

	inline bool apiUnHide(std::string const & fileName) {
		return SetFileAttributesA(fileName.c_str(), FILE_ATTRIBUTE_NORMAL) != 0 ? true : false;
	}

#endif 

#if defined (__unix__) || defined (__linix__)
#	define FS_HAS_OS_API_SUPPORT

	inline bool apiHideFile(std::string const &) {
		return true;
	}

	inline bool apiUnHide(std::string const &) {
		return true;
	}

#endif

#if !defined (FS_HAS_OS_API_SUPPORT)
#	error boost file system adapters(boost.inl) : OS not supported
#else
#	undef FS_HAS_OS_API_SUPPORT
#endif

	inline bool nativeHideFile(std::string const & fileName) {
		return apiHideFile(fileName);
	}

	inline bool nativeUnHideFile(std::string const & fileName) {
		return apiUnHide(fileName);
	}
}
}

#endif